home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume22 / nn6.4 / part09 < prev    next >
Encoding:
Internet Message Format  |  1990-06-07  |  54.4 KB

  1. Subject:  v22i044:  NN Newsreader, release 6.4, Part09/21
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: f84a93fc 2d9efbad e2cb911b 660525b3
  5.  
  6. Submitted-by: "Kim F. Storm" <storm@texas.dk>
  7. Posting-number: Volume 22, Issue 44
  8. Archive-name: nn6.4/part09
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then feed it
  12. # into a shell via "sh file" or similar.  To overwrite existing files,
  13. # type "sh file -c".
  14. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  15. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  16. # Contents:  doc/INSTALLATION man/nnacct.1m more.c
  17. # Wrapped by storm@texas.dk on Sun May  6 18:19:38 1990
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. echo If this archive is complete, you will see the following message:
  20. echo '          "shar: End of archive 9 (of 22)."'
  21. if test -f 'doc/INSTALLATION' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'doc/INSTALLATION'\"
  23. else
  24.   echo shar: Extracting \"'doc/INSTALLATION'\" \(23184 characters\)
  25.   sed "s/^X//" >'doc/INSTALLATION' <<'END_OF_FILE'
  26. X         CONFIGURATION AND INSTALLATION OF NN
  27. X         ------------------------------------
  28. X
  29. X                 RELEASE 6.4
  30. X
  31. X
  32. XThis file describes the necessary steps to configure and install nn.
  33. XYou are advised to read this file before proceeding with the installation.
  34. X
  35. XNOTE:    The configuration and installation has changed significantly
  36. X=====    from previous releases, so read these instructions carefully
  37. X    even if you are familiar with previous releases of nn.
  38. X
  39. XIf you want to use NNTP (accessing news from a remote host), you must
  40. Xalso read the file NNTP.
  41. X
  42. XThe files RELEASE_NOTES and PROBLEMS contains descriptions of problems
  43. Xpreviously seen when installing nn.  If you run into a problem, consult
  44. Xthat file before griping about it.
  45. X
  46. XThe following command line prompts are used in the examples:
  47. X   `$' is used when no special privileges are required.
  48. X   `#' is used when SUPER USER privileges may be required.
  49. X
  50. X
  51. X                STEP 1
  52. X
  53. X              CONFIGURATION OF MAKEFILE
  54. X              -------------------------
  55. X
  56. XCheck the 'Makefile' file and supply the proper values for the
  57. Xfollowing parameters:
  58. X
  59. XCC    The command to invoke the C compiler
  60. X
  61. XCPP    The command to invoke the C preprocessor with the result
  62. X    written to the standard output stream.
  63. X
  64. XCFLAGS    Flags to the C compiler  (e.g. -O or -g)
  65. X
  66. X
  67. X                STEP 2
  68. X
  69. X          CREATE CONFIGURATION FILE config.h
  70. X          ----------------------------------
  71. X
  72. XThe configuration file is distributed in the file config.h-dist.  You
  73. Xmust COPY this to config.h before proceeding.  Keep the original -dist
  74. Xfile to allow patches to be applied to it if necessary.
  75. X
  76. X    $ cp config.h-dist config.h
  77. X
  78. X
  79. X                STEP 3
  80. X
  81. X         EDIT config.h TO REFLECT YOUR SYSTEM
  82. X         ------------------------------------
  83. X
  84. XFor each required configuration parameter, the config.h file contains
  85. Xverbose comments explaining the meaning of each parameter in the file.
  86. XRead and follow these instructions carefully.  If you do that, nn
  87. Xshould compile and run without problems.
  88. X
  89. XFurther information about the parameters can be found below in case
  90. Xyou are in doubt.  Regarding the NNTP related definitions, consult the
  91. Xfile named NNTP.
  92. X
  93. XNotice that every time you edit config.h, the file update.h is
  94. Xmodified to make a new configuration level for the version in the
  95. Xsource directory.  The current configuration is showed in the version
  96. Xstring as #number.
  97. X
  98. X
  99. X       STEP 3.1: SPECIFY NETWORK AND NNTP CONFIGURATION
  100. X       ------------------------------------------------
  101. X
  102. XIf you use nn on a single system with news on its local disks, you
  103. Xwill not have to worry the least about networking, and you simply
  104. Xleave NETWORK_DATABASE and NNTP undefined.
  105. X
  106. XOtherwise, consult the file NNTP for further instructions on sharing
  107. Xthe news file and/or the database via NFS and/or NNTP.
  108. X
  109. X
  110. X             STEP 3.2: SELECT SYSTEM FILE
  111. X             ----------------------------
  112. X
  113. XAmong the things you have to select are two system and machine
  114. Xdependent files (residing in the `conf' subdirectory).  The following
  115. Xsystem files are delivered with nn:
  116. X
  117. X    s-3b1g.h    For 3b1 (unix-pc) with GCC.
  118. X    s-aix221.h    For AIX 2.2.1
  119. X    s-aux1-1.h    For A/UX 1.1
  120. X    s-bsd4-2.h    For 4.2 BSD and Ultrix systems
  121. X    s-bsd4-3.h    For 4.3 BSD systems
  122. X    s-dnix5-2.h    For dnix 5.2 on DIAB DS90.
  123. X    s-dnix5-3.h    For dnix 5.3 on DIAB DS90.
  124. X    s-dynix3-0.h    For Dynix 3.0 on Symmetry.
  125. X    s-fortune.h    For Fortune 32:16 [read comments in the file]
  126. X    s-hpux.h    For HPUX (series 300)
  127. X    s-hpux2-1.h    For HPUX 2.1 (series 800)
  128. X    s-hpux3-0.h    For HPUX 3.0 (series 800)
  129. X    s-hpux6-5.h    For HPUX 6.5 or newer (series 300)
  130. X    s-pyramid.h    For Pyramid (and Targon 35).
  131. X    s-sgi4D.h    For IRIX 3.1/3.2 [read comments in the file]
  132. X    s-sunos3.h    For SunOS 3
  133. X    s-sunos4-0.h    For SunOS 4.0
  134. X    s-sys5.h    For most system V based systems.
  135. X    s-sys5-tcap.h    For system V using termcap rather than terminfo.
  136. X    s-texas1500.h    For Texas Instruments System 1500.
  137. X    s-tower32.h    For NCR tower
  138. X    s-umipsb.h    For Mips running riscos 4.0 or greater
  139. X    s-uport2-2.h    For Microport UNIX V.2
  140. X    s-usg3-1.h    For most system V systems (obsolete)
  141. X    s-xenix386.h    For xenix386 [termcap version].
  142. X    s-xenix386ds.h    For Xenix386 2.3.2 w/development system.
  143. X
  144. XIf none of these can be used on your system, create your own based on
  145. Xthe file conf/s-template.h.
  146. X
  147. X
  148. X            STEP 3.3: SELECT MACHINE FILE
  149. X            -----------------------------
  150. X
  151. XThe following machine description files are delivered with nn:
  152. X
  153. X    m-3b1g.h    For 3b1 (unix-pc) with GCC [no networking].
  154. X    m-att3b.h    For AT&T 3b2 (with s-usg3-1.h)
  155. X    m-convex.h    For Convex.
  156. X    m-dec3100.h    For DECstation 3100 (with s-bsd4-2.h)
  157. X    m-gould.h    For Gould PN6000 (with s-bsd4-3.h)
  158. X    m-hp9000.h    For HP9000 series 320 and 800 (at least)
  159. X    m-i80286.h    For Intel 80286 processors [no network support]
  160. X    m-i80386.h    For Intel 80386 processors [no network support]
  161. X    m-m680x0.h    For Motorola 68000 family processors
  162. X    m-m88000.h    For Motorola 88000 risc processors
  163. X    m-mips.h    For MIPS processors
  164. X    m-pyramid.h    For Pyramid (and Targon 35).
  165. X    m-rt6150.h    For IBM 6150
  166. X    m-sgi4D.h    For Silicon Graphics 4D series.
  167. X    m-sparc.h    For SPARC processors
  168. X    m-sun386i.h    For 80386 based SUNs [have network support]
  169. X    m-symmetry.h    For Sequent Symmetry.
  170. X    m-vax.h        For VAX family
  171. X
  172. XIf you cannot use one of these machine files create your own based on
  173. Xthe file conf/m-template.h.
  174. X
  175. X
  176. X            STEP 3.4: LOCALIZE NN
  177. X            ---------------------
  178. X
  179. XYou will have to specify a number of files and directories which nn
  180. Xhas to know about to work properly.  If you don't specify these, nn
  181. Xwill in most cases use it own alternatives which will correspond to
  182. Xcommon practices on most installations.
  183. X
  184. XThe following directories and files can be defined in config.h:
  185. X
  186. X
  187. XBIN_DIRECTORY        (mandatory)
  188. X
  189. X    The directory where you want the user programs to be
  190. X    installed.  The following programs will be installed in that
  191. X    directory:
  192. X
  193. X    nn        The news reader program
  194. X    nnacct        Accounting, quota, and access management
  195. X    nnadmin        The administration program (link to nn)
  196. X    nncheck        Check for unread articles (link to nn)
  197. X    nngoback    Mark older articles as unread (link to nn)
  198. X    nngrab        Faster keyword search
  199. X    nngrep        Grep for news groups (link to nn)
  200. X    nnpost        Standalone posting program (link to nn).
  201. X    nnstats        Collection and expiration statistics
  202. X    nntidy        Cleans up the rc file (link to nn)
  203. X    nnusage        Show usage statistics
  204. X
  205. X
  206. XLIB_DIRECTORY
  207. X
  208. X    The directory where nn's auxiliary programs and files will
  209. X    be installed unless another directory is specified by one of
  210. X    the following definitions.
  211. X
  212. X
  213. XMASTER_DIRECTORY    (optional, default = LIB_DIRECTORY)
  214. X
  215. X    The directory containing the nnmaster daemon programs.  It
  216. X    should not be shared in a networked environment!
  217. X
  218. X    back_act
  219. X        Program to make daily copies of the active file to
  220. X        allow nngoback to work.
  221. X
  222. X    nnmaster
  223. X        The program building and maintaining nn's database.
  224. X
  225. X    nnspew    Program to build a tertiary subject database for
  226. X        nngrab.
  227. X
  228. X    MPID    Exclusive lock file created by the currently running
  229. X        nnmaster daemon process.  Accessed by nnadmin to
  230. X        get the daemon's process id.
  231. X
  232. X    GATE    Message file created by nnadmin and deleted by nnmaster.
  233. X
  234. X
  235. XCLIENT_DIRECTORY    (optional, default = LIB_DIRECTORY)
  236. X
  237. X    Contains the auxiliary programs and files required by the nn
  238. X    program:
  239. X
  240. X    aux    The shell script used in connection with replies etc.
  241. X        It knows about common editors like vi and gnu emacs to
  242. X        have them position the cursor appropriately.  To add
  243. X        support for your own favourite editor, you should edit
  244. X        the file aux.sh, not the compiled `aux' script!
  245. X
  246. X    upgrade_rc
  247. X        Script used by nn to convert release 6.3 rc files to
  248. X        .newsrc format when first invoked after upgrade to 6.4.
  249. X
  250. X
  251. XHELP_DIRECTORY        (optional, default = CLIENT_DIRECTORY/help)
  252. X
  253. X    The directory where the help files and online manual are
  254. X    stored.  This directory is an obvious candidate for sharing in
  255. X    a network.
  256. X
  257. X
  258. XCACHE_DIRECTORY        (optional, default = each user's .nn directory)
  259. X
  260. X    Only used with NNTP!! Directory to be used as a common storage
  261. X    for temporary cache files when nn is used with NNTP.  Using a
  262. X    common directory for cache files allows you to clean these out
  263. X    on reboot with a single "rm" command in the rc file:
  264. X         (cd CLIENT_DIRECTORY; rm -f *)
  265. X
  266. X
  267. XTMP_DIRECTORY        (optional, default = /usr/tmp)
  268. X
  269. X    The directory to be used as temporary storage for files used
  270. X    when editing responses etc.
  271. X
  272. X
  273. XNEWS_DIRECTORY        (optional, default = /usr/spool/news)
  274. X
  275. X    The directory containing the news spool directories and files.
  276. X    It is not required when a remote NNTP server is used.
  277. X
  278. X
  279. XNEWS_LIB_DIRECTORY    (optional, default = /usr/lib/news)
  280. X
  281. X    The directory containing the news system's active file and
  282. X    other related files.
  283. X
  284. X    When a remote NNTP server is used, it is still needed as the
  285. X    location of the (mini-)inews program if posting is allowed
  286. X    (unless INEWS is explicitly defined to override the default
  287. X    location).
  288. X
  289. X
  290. XLOG_FILE    (optional, default = LIB_DIRECTORY/Log)
  291. X
  292. X    The log file used by nnmaster and nn to store reports, error
  293. X    messages, usage statistics, etc.
  294. X
  295. X
  296. X          STEP 3.5: WHERE DO YOU WANT THE DATABASE?
  297. X          -----------------------------------------
  298. X
  299. XThe following definitions in config.h are used to control where the
  300. Xdatabase maintained by nnmaster is stored.  The database consists of a
  301. Xcouple of files containing global information for all existing groups,
  302. Xand a pair of files for each non-empty group.  The database requires
  303. Xsome disk space to hold the necessary information.  On average about
  304. X100 bytes per article in the system, or about 5% of the space
  305. Xallocated to the news articles.
  306. X
  307. XThe database is intended to be shared together with the news spool
  308. Xdirectory in a networked environment provided that NETWORK_DATABASE is
  309. Xdefined in config.h.
  310. X
  311. XIf DB_DIRECTORY is not defined, the global database files will be
  312. Xlocated in a directory named NEWS_DIRECTORY/.nn, and the per-group
  313. Xfiles will be located in each individual news group's directory (named
  314. X.nnd and .nnx).  Using this strategy will normally require that
  315. Xnnmaster is owned "news" (OWNER in config.h).
  316. X
  317. XThe location of the database can be changed via the following
  318. Xdefinitions in config.h:
  319. X
  320. XDB_DIRECTORY         (optional, default = see above)
  321. X    The directory containing the global database information files.
  322. X    If you share /usr/spool/news via NFS or RFS, you can set DB to
  323. X    something like /usr/spool/news/.nn to share it automatically
  324. X    with /usr/spool/news.
  325. X
  326. XDB_DATA_DIRECTORY    (optional, default = DB_DIRECTORY/DATA)
  327. X    When DB_DIRECTORY is defined, the per-group files will no
  328. X    longer be stored in the group directories, but in a single
  329. X    common directory specified by DB_DATA_DIRECTORY.  The files in
  330. X    this directory will be named either by group number or by
  331. X    group name (if DB_LONG_NAMES is also defined).
  332. X
  333. X
  334. XThe files config.h and NNTP describes how to share the database
  335. Xbetween several machines (also when you don't use NNTP).
  336. X
  337. X
  338. X                STEP 4
  339. X
  340. X             COMPILE THE SOFTWARE
  341. X             --------------------
  342. X
  343. XTo compile the software, you just have to run one of the following
  344. Xmake commands.
  345. X
  346. XIf you are making a complete package with both master and client, do
  347. X
  348. X    $ make all
  349. X
  350. XIf you want to share a database which resides on another host (through
  351. XNFS/RFS/rdist), you don't need a master on the local system, so you
  352. Xcan do the following instead:
  353. X
  354. X    $ make client
  355. X
  356. X
  357. X                STEP 5
  358. X
  359. X               INSTALLING THE SOFTWARE
  360. X               -----------------------
  361. X
  362. XInstallation of the nn software is handled entirely via a script
  363. X"./inst" created during the compilation.  The components of nn are
  364. Xsplit into five parts, which can be installed separately or in various
  365. Xcombinations depending on whether you run a stand-alone system or
  366. Xnetworked systems sharing the database and other parts of the nn
  367. Xpackage.  The five components are:
  368. X
  369. X1) Master files and programs (machine dependent)
  370. X   Install the MASTER_DIRECTORY programs.
  371. X
  372. X2) User files and programs (machince dependent, shareable)
  373. X   Install the BIN_DIRECTORY programs.
  374. X
  375. X3) Help files and auxiliary programs (shareable)
  376. X   Install the CLIENT_DIRECTORY and HELP_DIRECTORY files and programs.
  377. X
  378. X4) Documentation (shareable)
  379. X   Install the MAN pages in the proper directories.
  380. X
  381. X5) Online manual (shareable with 3)
  382. X   Format and install the online manual in HELP_DIRECTORY.
  383. X
  384. X
  385. XUnless you have defined yourself as the owner of the nn package and
  386. Xhave write permission on all the necessary directories, you will need
  387. Xto be super-user to install nn, so start with
  388. X
  389. X    $ su
  390. X
  391. XNow run the installation script:
  392. X
  393. X    # ./inst
  394. X
  395. XThe `inst' script will list a menu with the following choices:
  396. X
  397. X(1)-(5)    Install individual parts of the package.
  398. X
  399. X(s)    Install a complete server + client package (1-5).
  400. X
  401. X(c)    Install a client which accesses all its support files and
  402. X    the database via a network (2).
  403. X
  404. X(n)    Install a client accessing only the database via a network (2-5).
  405. X
  406. X(m)    Install only the nnmaster (1).
  407. X
  408. X(c)    Install only the client programs (2).
  409. X
  410. X(u)    Update already installed parts of the package.  This will
  411. X    check for the existence of the old programs, and only update
  412. X    programs and files already installed.  You will typically use
  413. X    this after applying patches.
  414. X
  415. XYou can also run the `inst' script with the choices as arguments, e.g.
  416. X
  417. X    ./inst m c
  418. X
  419. X
  420. XNOTICE: Since nnmaster runs setuid OWNER, all users can potentially
  421. X    kill the running master, initialize the database etc. if they
  422. X    have access to execute the master.  So either restrict the
  423. X    permissions to execute nnmaster or the access to the directory
  424. X    containing it.  The default installation puts modes -rwsr-x---
  425. X    on nnmaster and leaves the directory "open" which may not be
  426. X    adequate for you.
  427. X
  428. X
  429. X                STEP 6
  430. X
  431. X               INITIALIZE THE DATABASE
  432. X               -----------------------
  433. X
  434. XIf you have installed the nnmaster on the current system, you now have
  435. Xto initialize the database:
  436. X
  437. X    $ su         -- also as superuser
  438. X    # ./inst INIT
  439. X
  440. XIf something goes wrong in this step, e.g. problems with the active
  441. Xfile, you must redo the initialization after fixing the other
  442. Xproblems.
  443. X
  444. XWhen the INIT operation completes, a database with empty entries for
  445. Xall the currently existing groups will have been created.  If you want
  446. Xsome special actions to be performed for specific groups as described
  447. Xin the nnmaster manual, you must now edit the GROUPS file created by
  448. Xnnmaster in the DB_DIRECTORY.  If you modify the GROUPS file, you must
  449. Xrun the following command to register the changes to the GROUPS file.
  450. X    nnmaster -G
  451. X
  452. XWhen you are ready, you must start nnmaster to enter all the existing
  453. Xarticles into the database.  If you use the following command,
  454. Xnnmaster will fork and return immediately; its background child will
  455. Xcontinue to update the database whenever new articles arrive:
  456. XIt will ignore articles which are more than 45 days old (-O).
  457. X
  458. X    $ MASTER_DIRECTORY/nnmaster -r -O45
  459. X
  460. XIt may take quite a while before all existing articles have been
  461. Xentered into the database.  You can use nnadmin's (U)pdate and (S)tat
  462. Xcommands to trace the progress and the (L)og command to see if it has
  463. Xfinished (a C entry will occur).  You will see that many groups will
  464. Xbe BLOCKED, but the number should decrease as nnmaster gets through
  465. Xmore and more groups.
  466. X
  467. XYou can also use the following command to do the initial collection of
  468. Xarticles from a terminal and get a nice trace of the action:
  469. X
  470. X    nnmaster -D -O45
  471. X
  472. XOne or two numbers will be shown while a group is being collected.
  473. XThe first number is the number of the article currently being read.
  474. XThe (optional) second number will be the number of old (or bad)
  475. Xarticles which nnmaster has ignored in the group so far.
  476. X
  477. X
  478. XNOTICE: If the system file you have used does not specify how to
  479. X    detatch a process from its controlling terminal, the nnmaster
  480. X    may die when you log out.
  481. X
  482. XWhen nnmaster has finished the initial collection the articles, you
  483. Xcan nnadmin's (V)alidate command to verify that the database build by
  484. Xnnmaster is consistent (restart nnadmin before verifying).
  485. X
  486. X
  487. X                STEP 7
  488. X
  489. X             UPDATE SYSTEM FILES
  490. X             -------------------
  491. X
  492. XYou will have to edit some of the scripts and files on your system to
  493. Xget the database and other support files updates automatically, also
  494. Xfollowing system shutdown, crashes, etc.
  495. X
  496. X
  497. X        STEP 7.1: START NNMASTER WHEN SYSTEM IS BOOTED
  498. X        ----------------------------------------------
  499. X
  500. XTo have the database updated at all times, the nnmaster should be
  501. Xstarted when the system is booted.
  502. X
  503. XThere will be a file named /etc/rc, a directory /etc/rc.d, or
  504. Xsomething similar on your system which contains commands that are
  505. Xexecuted when the system is booted.  The following commands should be
  506. Xadded to the boot scripts:
  507. X
  508. X    rm -f MASTER_DIRECTORY/MPID
  509. X    MASTER_DIRECTORY/nnmaster -l -r -C
  510. X
  511. X
  512. XAlternatively, you can arrange for cron to run the master regularly.
  513. XIn this case, you should not use the -r and -C options.  Instead, you
  514. Xshould let cron execute the command 'nnadmin Z' once a day to
  515. Xvalidate the database.  For example:
  516. X
  517. X    0,10,20,30,40,50 * * * * MASTER/nnmaster -LM
  518. X    0 0 * * * BIN/nnadmin Z
  519. X
  520. X
  521. XWARNING: If you share the database via NFS or RFS, nnmaster should run
  522. X     only on the system where the database actually resides!!
  523. X     And preferably it should run on the host where the news spool
  524. X     directory is located as well.  This will improve speed as well
  525. X     as reliability (NFS can suffer from time out problems).
  526. X
  527. X
  528. X        STEP 7.2: SETUP EXPIRE ON THE DATABASE
  529. X        --------------------------------------
  530. X
  531. XTo run expire on the database, you simply have to execute the
  532. Xfollowing command (with sufficient privileges):
  533. X
  534. X    BIN_DIRECTORY/nnadmin =EYW
  535. X
  536. XYou should arrange for expire to be run on nn's database whenever you
  537. Xhave run expire on the news directories.
  538. X
  539. XSupposing you run the expire from your crontab, you may simply add the
  540. Xabove command to the crontab at an appropriate time when you are
  541. Xcertain that news' expire is completed.
  542. X
  543. XIf you run nnmaster from cron rather than in daemon mode, you can use
  544. Xthe following command to run expire on the database.
  545. X
  546. X    nnmaster -F -k ""
  547. X
  548. XThis form allows you to run expire on selected groups rather than on
  549. Xall groups as initiated by the above nnadmin command.  See the
  550. Xnnmaster manual for further details.
  551. X
  552. X
  553. X     STEP 7.3: SAVE A COPY OF THE ACTIVE FILE ONCE A DAY
  554. X     ---------------------------------------------------
  555. X
  556. XThe `nngoback' program requires that the program `back_act' is
  557. Xexecuted once (and only once) every day to maintain suitable copies of
  558. Xthe active files for the last 14 days.  In a network environment, it
  559. Xshould execute on the same host as the nnmaster.
  560. X
  561. XSimply arrange for back_act to be invoked by cron once a day
  562. X(preferably just before the batch of news for `today' arrives).  For
  563. Xexample, assuming the news is received just before midnight (syntax
  564. Xand location of crontab entry may vary):
  565. X
  566. XIn /usr/spool/cron/crontabs/news (System V):
  567. X    00 23 * * * MASTER_DIRECTORY/back_act
  568. Xor in /usr/lib/crontab (BSD):
  569. X    00 23 * * * su - news MASTER_DIRECTORY/back_act
  570. X
  571. X
  572. X      STEP 7.4:  PREPARE FOR NNSPEW TO BE RUN REGULARLY
  573. X      -------------------------------------------------
  574. X
  575. XThe nngrab program will run faster if a dedicated subject database in
  576. Xaddition to the normal database is available.  To maintain this
  577. Xadditional database, the program nnspew must be executed regularly,
  578. Xe.g. from cron.  Every 3-6 hours should be sufficient to keep the
  579. Xdatabase reasonably up-to-date, e.g.
  580. X
  581. XIn /usr/spool/cron/crontabs/news (System V):
  582. X    2 6,12,18 * * * MASTER_DIRECTORY/nnspew
  583. Xor in /usr/lib/crontab (BSD):
  584. X    2 6,12,18 * * * su - news MASTER_DIRECTORY/nnspew
  585. X
  586. X
  587. X                STEP 8
  588. X
  589. X            INSTALL AND EDIT GLOBAL FILES
  590. X            -----------------------------
  591. X
  592. XDepending on your needs, you should create the following files on each
  593. Xhost running nn (you may also just share the files if you like):
  594. X
  595. XCLIENT_DIRECTORY/init
  596. X    The global init file for all users on the system.  Users will
  597. X    be able to override the definitions in this file, but you can
  598. X    probably make some sensible decisions which will prevent
  599. X    novice users from getting into trouble, for example set the
  600. X    default distribution to "local" etc.
  601. X
  602. X    You can also specify a global presentation sequence here.
  603. X
  604. X    You may use init.sample as a starting point, but don't use it
  605. X    without careful examination.  Especially, the sequence part
  606. X    is mainly an illustration of the possibilities.  If you are in
  607. X    doubt, just delete the sequence part of the file (groups will
  608. X    then be presented in pure alphabetical order).
  609. X
  610. XCLIENT_DIRECTORY/routes
  611. X    You DO NOT NEED this file if you already run a domain based
  612. X    mailer, i.e. when HAVE_ROUTING is defined in config.h.
  613. X
  614. X    Otherwise, you can use it as a configuration file for the
  615. X    domain address remapping done by nn in reply addresses and the
  616. X    nnmail program.  You may use routes.sample as a starting point
  617. X    (it briefly describes how to build a routes file).
  618. X
  619. X    Please notice that neither the routes functionality, nor
  620. X    nnmail is a supported part of nn - if you really want to
  621. X    run a domain-based mailer, get smail 2.5 or later.  And if you
  622. X    ask me how to use it I will answer: "Get SMAIL instead".
  623. X
  624. X
  625. XNNTP_SERVER
  626. X    Must contain the host name of the NNTP-server when NNTP is
  627. X    used.  If you already run NNTP with your other news readers,
  628. X    this file does not need to be modified.
  629. X
  630. X
  631. X                STEP 9
  632. X
  633. X               TEST THE BASIC FUNCTIONS
  634. X               ------------------------
  635. X
  636. XIf any of the following tests fails or you see other peculiar
  637. Xbehaviour, you should consult the PROBLEMS file.  You may not be the
  638. Xonly one to have seen the problems, and there might even be a solution.
  639. X
  640. XFirst you should check that nnmaster does collect the articles it is
  641. Xsupposed to.  Here, nnadmin is a great help, since you can peek around
  642. Xin all the database files and see what nnmaster is doing.  nnadmin
  643. Xtakes a snap-shot of the database when it starts up, but you can take
  644. Xa new snap-shot anytime using the (U)pdate command.
  645. X
  646. XAlso look at the (L)og to see that there were no problems while
  647. Xcollecting the articles.
  648. X
  649. XThere are a few things you should check to ensure the proper
  650. Xfunctioning of nn.
  651. X
  652. X1) Backup your current .newsrc file if you have one.  (Don't save it
  653. X   in .newsrc.bak or .newsrc.orig since nn may use these names).
  654. X
  655. X2) Run `nn'.  If you have upgraded from release 6.3, nn will convert
  656. X   your release 6.3 .nn/rc file into a .newsrc file.
  657. X
  658. X3) Does nn find any news?  If not, does nn -x find anything?
  659. X
  660. X4) Can you send mail to yourself?  Try the sequence:
  661. X    m (return) (return) testing (return)
  662. X    edit the letter
  663. X    s (return)
  664. X
  665. X   If not, you should check the REC_MAIL program.
  666. X
  667. X5) Can you post an article to the local test group?  Try:
  668. X    :post (return)
  669. X       test (return)
  670. X       local (return)
  671. X    edit the article
  672. X    s (return)
  673. X
  674. X   If not, you should check the INEWS program.
  675. X
  676. X
  677. X         -------------------------------------------
  678. X             IF EVERYTHING WORKS
  679. X         YOU HAVE COMPLETED THE INSTALLATION
  680. X         -------------------------------------------
  681. X
  682. X
  683. X            UPDATING THE SOFTWARE
  684. X            ---------------------
  685. X
  686. XPatches to this software will be distributes as context diff's which
  687. Xcan be applied using Larry Wall's `patch' program.
  688. X
  689. XAfter applying the patches, you will need to redo the compilation and
  690. Xinstallation steps:
  691. X
  692. X    $ patch < PATCH_FILE    (or use nn's :patch command)
  693. X    $ make all
  694. X    $ su
  695. X    # ./inst u
  696. X
  697. XTo be able to install a new nnmaster, the currently running master (if
  698. Xany) will be stopped automatically, and it has to be started manually
  699. Xwhen the installation is complete (unless it is setup to be run by cron).
  700. X
  701. XNotice that unless it is explicitly required in the patch, there is no
  702. Xneed to reinitialize the database after applying the patch.
  703. END_OF_FILE
  704.   if test 23184 -ne `wc -c <'doc/INSTALLATION'`; then
  705.     echo shar: \"'doc/INSTALLATION'\" unpacked with wrong size!
  706.   fi
  707.   # end of 'doc/INSTALLATION'
  708. fi
  709. if test -f 'man/nnacct.1m' -a "${1}" != "-c" ; then 
  710.   echo shar: Will not clobber existing file \"'man/nnacct.1m'\"
  711. else
  712.   echo shar: Extracting \"'man/nnacct.1m'\" \(3905 characters\)
  713.   sed "s/^X//" >'man/nnacct.1m' <<'END_OF_FILE'
  714. X.TH NNACCT 1m "Release 6.4"
  715. X.UC 4
  716. X.SH NAME
  717. Xnnacct \- news accounting and access authorization (nn)
  718. X.SH SYNOPSIS
  719. X\fBnnacct\fP \-\fBr\fP [ \-\fBf\fP file ] [ \-\fBa\fP ] [ user ]...
  720. X.br
  721. X\fBnnacct\fP \-\fBp\fP\fIpolicy\fP \-\fBq\fP\fIquota\fP user...
  722. X.SH DESCRIPTION
  723. XThe \fInnacct\fP command provides an optional accounting and access
  724. Xauthorization for news reading via the \fInn\fP news reader.
  725. X.LP
  726. XThe first form (\-\fBr\fP) is used to print accounting reports.
  727. XIf a \fIfile\fP is specified data from a saved accounting file;
  728. Xotherwise the data is read from the current accounting file.
  729. X.LP
  730. XIf \-\fBa\fP is specified, the report will contain accounting data for
  731. X\fIall\fP users.  Otherwise, if one or more \fIusers\fP are specified,
  732. Xthe data for these users will be printed.  If neiter is specified,
  733. Xonly the accounting data for the current user is printed.
  734. X  Only the super-user can generate reports for other users than the
  735. Xcaller.
  736. X.LP
  737. XThe second form (\-\fBp\fP and/or \-\fBq\fP) assigns the specified
  738. Xaccess \fIpolicy\fP and/or \fIquota\fP to the specified users.  If a
  739. Xgiven user is not already known in the accounting file, a new entry
  740. Xwith the specified policy and quota is created (default values are
  741. Xused if both are not specified).
  742. X.LP
  743. XThe following policies are currently implemented:
  744. X.TP
  745. X\fB0\fP
  746. XNo access.  The user is not allowed to read news at all.
  747. X.TP
  748. X\fB1\fP
  749. XPrivileged user.  The user can read news at all times and no
  750. Xaccounting information is saved.  This is obviously the policy for
  751. Xsystem administrators :-)
  752. X.TP
  753. X\fB2\fP
  754. XFull time access.  The user can access news at all times.
  755. X.TP
  756. X\fB3\fP
  757. XOff-hours access.  The user can only access news at off hours, i.e. in
  758. Xthe morning, in the evening, on week-ends, and on holidays (not
  759. Xcomplete \- check the source :-)
  760. X.LP
  761. XThe \fIquota\fP specifies a number of \fIhours\fP which the user is
  762. Xallowed to read news.  When this quota is used up, access will be
  763. Xblocked.  A quota of zero gives unlimited access.
  764. X.LP
  765. XNew users will get the \fIdefault policy\fP and \fIquota\fP defined in
  766. Xaccount.c.  If this allows new users to read news at only specific
  767. Xtimes, this form can be used to permit individual users to read news
  768. Xat all times, or it can be used to prevent them from reading news at
  769. Xall.  If the default policy does not allow new users to read news,
  770. Xthis form must be used to authorize them to read news.
  771. X.SH HOW IT WORKS
  772. XIf authorization is enabled, the \fInn\fP news reader will call
  773. X\fInnacct\fP on start-up to check whether the policy and quota defined
  774. Xfor the current user allows him to read news at this time (or at all).
  775. X.LP
  776. XIf accounting is enabled, the \fInn\fP news reader will call
  777. X\fInnacct\fP on exit to register the time spent on news reading.
  778. XIf account logging is also defined (see account.c), an line is also
  779. Xadded to the accounting log file.
  780. X.LP
  781. XWhen accounting is defined, the user can use the \fB:cost\fP command
  782. Xto get the current accounting data, and if the variable
  783. X\fBreport-cost\fP is set, \fInn\fP will print accounting information
  784. Xon exit.
  785. X.SH CONTIGURATION AND NEW POLICIES
  786. XThe use of \fInnacct\fP is enabled via the ACCOUNTING and
  787. XAUTHORIZE symbols in \fInn\fP's configuration file.  Further
  788. Xconfiguration of cost calculations, logging, default policy, default
  789. Xquotas, etc. is done directly in the source file \fIaccount.c\fP.  New
  790. Xaccess policies can also be defined in this file.  This allows you to
  791. Xchange the policies or prices without having to recompile the whole
  792. Xpackage since only \fInnacct\fP is modified.
  793. X.SH FILES
  794. X.DT
  795. X.ta \w'$db/acctlog'u+3m
  796. X.\"ta 0 16
  797. X$db/acct    accounting data (accumulated per user)
  798. X.br
  799. X$db/acctlog    accounting log (grows indefinitely)
  800. X.DT
  801. X.SH SEE ALSO
  802. Xnn(1), nnusage(1)
  803. X.SH BUGS
  804. XThere should be some tools to mess around with the accounting files,
  805. Xe.g. to make summaries, clear usage counters, etc.
  806. X.SH AUTHOR
  807. XKim F. Storm, Texas Instruments A/S, Denmark
  808. X.br
  809. XE-mail: storm@texas.dk
  810. END_OF_FILE
  811.   if test 3905 -ne `wc -c <'man/nnacct.1m'`; then
  812.     echo shar: \"'man/nnacct.1m'\" unpacked with wrong size!
  813.   fi
  814.   # end of 'man/nnacct.1m'
  815. fi
  816. if test -f 'more.c' -a "${1}" != "-c" ; then 
  817.   echo shar: Will not clobber existing file \"'more.c'\"
  818. else
  819.   echo shar: Extracting \"'more.c'\" \(24124 characters\)
  820.   sed "s/^X//" >'more.c' <<'END_OF_FILE'
  821. X/*
  822. X *    (c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
  823. X *
  824. X *    Article browser.
  825. X */
  826. X
  827. X#include "config.h"
  828. X#include "news.h"
  829. X#include "term.h"
  830. X#include "menu.h"
  831. X#include "keymap.h"
  832. X#include "regexp.h"
  833. X
  834. Xexport int  monitor_mode = 0;
  835. Xexport int  compress_mode = 0;
  836. Xexport int  show_article_date = 1;
  837. Xexport int  first_page_lines = 0;
  838. Xexport int  overlap = 2;
  839. Xexport int  mark_overlap = 0;
  840. Xexport char *header_lines = NULL;
  841. Xexport int  min_pv_window = 7;
  842. Xexport int  wrap_headers = 6;
  843. Xexport int  data_bits = 7;
  844. Xexport int  scroll_clear_page = 1;
  845. Xexport int  expired_msg_delay = 1;
  846. X
  847. Ximport int  preview_window;
  848. Ximport int  novice;
  849. Ximport int  slow_mode;
  850. Ximport int  auto_preview_mode;
  851. Ximport int  flush_typeahead;
  852. Ximport int  case_fold_search;
  853. X
  854. Ximport char delayed_msg[];
  855. X
  856. Xextern char *init_save();
  857. X
  858. Xstatic int rot13_must_init = 1;
  859. Xstatic char rot13_table[128];
  860. Xexport int rot13_active = 0;
  861. X#define ROT13_DECODE(c)     ((c & 0x80) ? c : rot13_table[c])
  862. X
  863. Xstatic int compress_space;
  864. X
  865. Xstatic regexp *regular_expr = NULL;
  866. X
  867. X#define LINEMAX    100        /* most articles are less than 100 lines */
  868. X
  869. Xstatic struct header_def {
  870. X    char field;
  871. X    char *text;
  872. X    char **news;
  873. X    char **digest;
  874. X} header_defs[] = {
  875. X    'A', "Approved",    &news.ng_appr,        0,
  876. X    'B', "Distribution",&news.ng_dist,        0,
  877. X    'D', "Date",    &news.ng_date,        &digest.dg_date,
  878. X    'F', "From",    &news.ng_from,        &digest.dg_from,
  879. X    'I', "Message-Id",    &news.ng_ident,        0,
  880. X    'K', "Keywords",    &news.ng_keyw,        0,
  881. X    'L', "Lines",    &news.ng_xlines,    0,
  882. X    'N', "Newsgroups",    &news.ng_groups,    0,
  883. X    'O', "Organization",&news.ng_org,        0,
  884. X    'P', "Path",    &news.ng_path,        0,
  885. X    'R', "Reply-To",    &news.ng_reply,        0,
  886. X    'S', "Subject",    &news.ng_subj,        &digest.dg_subj,
  887. X    'W', "Followup-To",    &news.ng_follow,    0,
  888. X    'X', "References",    &news.ng_ref,        0,
  889. X    'Y', "Summary",    &news.ng_summ,        0,
  890. X    'd', "Date-Received", &news.ng_rdate,    0,
  891. X    'n', "Newsgroups",    &news.ng_groups,    0,
  892. X    'x', "Back-Ref",    &news.ng_bref,        0,
  893. X    0
  894. X};
  895. X
  896. Xstatic char *a_st_flags(flag)
  897. Xflag_type flag;
  898. X{
  899. X    static char buf[40];
  900. X    register char *cp;
  901. X    static flag_type prevflag = 0;
  902. X
  903. X    flag &= A_ST_FILED | A_ST_REPLY | A_ST_FOLLOW;
  904. X    if (flag == 0) {
  905. X    prevflag = 0;
  906. X    return "";
  907. X    }
  908. X
  909. X    if (flag == prevflag) return buf;
  910. X    prevflag = flag;
  911. X
  912. X    cp = buf;
  913. X    *cp++ = '(';
  914. X    if (flag & A_ST_FILED) {
  915. X    *cp++ = 'F';
  916. X    *cp++ = 'i';
  917. X    *cp++ = 'l';
  918. X    *cp++ = 'e';
  919. X    *cp++ = 'd';
  920. X    }
  921. X
  922. X    if (flag & A_ST_REPLY) {
  923. X    if (cp[-1] != '(') *cp++ = SP;
  924. X    *cp++ = 'R';
  925. X    *cp++ = 'e';
  926. X    }
  927. X
  928. X    if (flag & A_ST_FOLLOW) {
  929. X    if (cp[-1] != '(') *cp++ = SP;
  930. X    *cp++ = 'F';
  931. X    *cp++ = 'o';
  932. X    *cp++ = 'l';
  933. X    }
  934. X
  935. X    strcpy(cp, ")------");
  936. X    return buf;
  937. X}
  938. X
  939. Xmore(ah, mode, screen_offset)
  940. Xarticle_header *ah;
  941. Xint mode, screen_offset;
  942. X{
  943. X    register int c, col, lno;
  944. X    register FILE *art;
  945. X    int more_cmd, eof, skip_spaces, has_space, window_lines;
  946. X    int form_feed, last_ff_line, ignore_nl;
  947. X    off_t firstl, lastl;
  948. X    off_t lineposbuf[LINEMAX];
  949. X    off_t *linepos = lineposbuf;
  950. X    int linemax = LINEMAX;
  951. X    char linebuf[200], *lp, skip_char;
  952. X    int skip_wrap;
  953. X    news_header_buffer ngheader, dgheader;
  954. X    struct news_header news_save;
  955. X    struct digest_header digest_save;
  956. X    int linenum, maxline, topline, print_lines, lno1;
  957. X    int underline_line, fake_underline;
  958. X    int match_lines, match_redraw, match_topline, match_botline;
  959. X    int goto_line, prev_goto, stop_line, extra_lines;
  960. X    flag_type in_digest = ah->flag & A_DIGEST;
  961. X    article_header digestah;
  962. X    char *fname, *hdrline;
  963. X    extern STANDOUT;
  964. X    char pr_fmt[60], send_date[40];
  965. X    int match_expr;
  966. X    char *match_start, *match_end;
  967. X    int open_modes, hdr_mode, o_mode;
  968. X    struct header_def *hdef;
  969. X    extern int alt_cmd_key, in_menu_mode, any_message;
  970. X#ifdef RESIZING
  971. X    int entry_col = Columns;
  972. X#endif
  973. X    extern char *pct();
  974. X
  975. X#define more_return(cmd) \
  976. X    { more_cmd = cmd; goto more_exit; }
  977. X
  978. X    if (ah->a_group != NULL) init_group(ah->a_group);
  979. X
  980. X    open_modes = SKIP_HEADER;
  981. X    if (show_article_date || header_lines) {
  982. X    open_modes |= FILL_NEWS_HEADER;
  983. X    if (header_lines == NULL)
  984. X        open_modes |= GET_DATE_ONLY;
  985. X    else
  986. X        open_modes |= GET_ALL_FIELDS;
  987. X    if (in_digest) open_modes |= FILL_DIGEST_HEADER;
  988. X    }
  989. X
  990. X    art = open_news_article(ah, open_modes, ngheader, dgheader);
  991. X
  992. X    if (art == NULL) {
  993. X    if (expired_msg_delay >= 0) {
  994. X        msg("Expired: \"%s: %-.50s\"", ah->sender, ah->subject);
  995. X        if ((mode & MM_PREVIEW) == 0 && expired_msg_delay > 0)
  996. X        user_delay(expired_msg_delay);
  997. X    }
  998. X    return MC_NEXT;
  999. X    }
  1000. X
  1001. X    o_mode = in_menu_mode;
  1002. X    in_menu_mode = 0;
  1003. X
  1004. X    if (screen_offset)
  1005. X    if (preview_window < 1 && Lines - screen_offset < min_pv_window)
  1006. X        screen_offset = 0;
  1007. X        else {
  1008. X        so_printxy(0, screen_offset++, "%s: %s ", ah->sender, ah->subject);
  1009. X        if (!STANDOUT) screen_offset++;
  1010. X        clrline();
  1011. X    }
  1012. X
  1013. X    if (show_article_date) {
  1014. X    if (in_digest && digest.dg_date)
  1015. X        strncpy(send_date, digest.dg_date, 40);
  1016. X    else
  1017. X        if (news.ng_date) {
  1018. X        strncpy(send_date, news.ng_date, 40);
  1019. X        } else
  1020. X        send_date[0] = NUL;
  1021. X    send_date[39] = NUL;
  1022. X    if (lp = strrchr(send_date, ':')) *lp = NUL;
  1023. X    }
  1024. X
  1025. X    linepos[0] = ah->hpos;
  1026. X    linepos[1] = firstl = ah->fpos;
  1027. X    maxline = 1;
  1028. X    topline = 1;
  1029. X    hdrline = screen_offset == 0 ? header_lines : "";
  1030. X
  1031. X    lastl = (ah->lpos - firstl + 99)/100;
  1032. X    if (lastl == 0) lastl = 1;    /* impossible ? */
  1033. X
  1034. X    rot13_active = 0;
  1035. X    compress_space = compress_mode;
  1036. X    last_ff_line = goto_line = -1, prev_goto = 1;
  1037. X    skip_char = NUL; skip_wrap = 0;
  1038. X    match_lines = match_redraw = match_expr = 0;
  1039. X    underline_line = -1;
  1040. X    fake_underline = 0;
  1041. X
  1042. X    stop_line = first_page_lines ? first_page_lines : -1;
  1043. X
  1044. X    sprintf(pr_fmt,
  1045. X        "\1\2-- %s%s %s-----%%s%s-----%%s\1",
  1046. X        (mode & MM_PREVIEW) ? "PREVIEW " : "",
  1047. X        (mode & MM_DIGEST) ? "FULL DIGEST" :
  1048. X        (mode & MM_LAST_SELECTED) ? "LAST ARTICLE" : "ARTICLE",
  1049. X        novice ? "-- help:? " : "",
  1050. X        (ah->flag & A_NEXT_SAME) ? " (+next)" : "");
  1051. X
  1052. X    if (screen_offset) goto safe_redraw;
  1053. X
  1054. X redraw:        /* redraw that will destroy whole screen */
  1055. X    screen_offset = 0;
  1056. X
  1057. X safe_redraw:     /* redraw of "more window" only */
  1058. X    linenum = topline;
  1059. X
  1060. X next_page:
  1061. X    no_raw();
  1062. X
  1063. X    s_keyboard = 0;
  1064. X
  1065. X    if (stop_line) {
  1066. X    lno = screen_offset;
  1067. X    if (scroll_clear_page || linenum <= 1) {
  1068. X        if (lno) {
  1069. X        gotoxy(0, lno);
  1070. X        clrpage(lno);
  1071. X        } else
  1072. X        clrdisp();
  1073. X    }
  1074. X
  1075. X    if (linenum == 1)
  1076. X        hdrline = screen_offset == 0 ? header_lines : "";
  1077. X
  1078. X      print_header:
  1079. X    if (hdrline == NULL || *hdrline == '*') {
  1080. X        if (hdrline && *++hdrline == NUL) hdrline = NULL;
  1081. X
  1082. X        if (linenum <= 1) {
  1083. X        if (linenum == 0 || (mode & MM_DIGEST)) {
  1084. X            if (screen_offset) {
  1085. X            lno--;
  1086. X            if (!STANDOUT) lno--;
  1087. X            gotoxy(0, lno);
  1088. X            }
  1089. X
  1090. X            so_printxy(0, lno,
  1091. X                   "Newsgroup: %s, article: %ld%s",
  1092. X                   current_group->group_name,
  1093. X                   (long)(ah->a_number),
  1094. X                   ((mode & MM_DIGEST) || in_digest)
  1095. X                   ? "  *DIGEST*" : "");
  1096. X/*            fseek(art, linepos[0], 0); */
  1097. X
  1098. X            lno++;
  1099. X            if (!STANDOUT) lno++;
  1100. X        } else {
  1101. X            if (screen_offset == 0 && linenum == 1) {
  1102. X            if (show_article_date) so_printxy(-1, 0, send_date);
  1103. X
  1104. X            /* so_printxy will cut subject */
  1105. X            so_printxy(0, lno, "%s: %s ", ah->sender, ah->subject);
  1106. X            lno++;
  1107. X            if (!STANDOUT) lno++;
  1108. X            }
  1109. X        }
  1110. X        }
  1111. X    }
  1112. X
  1113. X    if (hdrline && screen_offset == 0) {
  1114. X
  1115. X        hdr_mode = 0;
  1116. X        while (*hdrline) {
  1117. X
  1118. X        if (*hdrline == '*') goto print_header;
  1119. X
  1120. X        if (*hdrline == '=') {
  1121. X            hdr_mode = 1;
  1122. X            hdrline++;
  1123. X            continue;
  1124. X        }
  1125. X        if (*hdrline == '_') {
  1126. X            hdr_mode = 2;
  1127. X            hdrline++;
  1128. X            continue;
  1129. X        }
  1130. X        for (hdef = header_defs; hdef->field; hdef++) {
  1131. X            if (hdef->field != *hdrline) continue;
  1132. X            if (in_digest) {
  1133. X            if (hdef->digest == NULL) break;
  1134. X            if ((lp = *(hdef->digest)) == NULL)
  1135. X                break;
  1136. X            } else
  1137. X            if ((lp = *(hdef->news)) == NULL)
  1138. X                break;
  1139. X            if (*hdrline == 'n')
  1140. X            if ((current_group->group_flag & G_MERGED) == 0 &&
  1141. X                strchr(lp, ',') == NULL) break;
  1142. X
  1143. X            gotoxy(0, lno++);
  1144. X            printf("%s: ", hdef->text);
  1145. X            c = col = strlen(hdef->text) + 2;
  1146. X         split_header_line:
  1147. X            switch (hdr_mode) {
  1148. X             case 0:
  1149. X            break;
  1150. X             case 1:
  1151. X            highlight(1);
  1152. X            break;
  1153. X             case 2:
  1154. X            underline(1);
  1155. X            break;
  1156. X            }
  1157. X            while (*lp && c < Columns) {
  1158. X            if (isspace(*lp)) {
  1159. X                while (lp[1] && isspace(lp[1])) lp++;
  1160. X                if (wrap_headers > 0 &&
  1161. X                (c + wrap_headers) >= Columns &&
  1162. X                strlen(lp) >= wrap_headers) {
  1163. X                lp++;
  1164. X                break;
  1165. X                }
  1166. X                *lp = SP;
  1167. X            }
  1168. X            putchar(*lp++);
  1169. X            c++;
  1170. X            }
  1171. X            switch (hdr_mode) {
  1172. X             case 0:
  1173. X            break;
  1174. X             case 1:
  1175. X            highlight(0);
  1176. X            break;
  1177. X             case 2:
  1178. X            underline(0);
  1179. X            break;
  1180. X            }
  1181. X            if (*lp && wrap_headers >= 0) {
  1182. X            gotoxy(col, lno++);
  1183. X            c = col;
  1184. X            goto split_header_line;
  1185. X            }
  1186. X            break;
  1187. X        }
  1188. X        hdr_mode = 0;
  1189. X        hdrline++;
  1190. X        }
  1191. X
  1192. X        hdrline = NULL;
  1193. X        putchar(NL);
  1194. X        lno++;
  1195. X    }
  1196. X
  1197. X    lno1 = lno;
  1198. X    topline = linenum;
  1199. X
  1200. X    window_lines = Lines - lno - 2;
  1201. X    print_lines = window_lines;
  1202. X
  1203. X    ignore_nl = 1;    /* ignore blank lines at top op screen */
  1204. X    } else {
  1205. X    putchar(CR);
  1206. X    clrline();
  1207. X    print_lines = extra_lines;    /* LINT complaints here -- ignore */
  1208. X    }
  1209. X
  1210. X    if (stop_line > 0) {
  1211. X    if (print_lines > stop_line) {
  1212. X        extra_lines = print_lines - stop_line;
  1213. X        print_lines = stop_line;
  1214. X        underline_line = -1;
  1215. X    }
  1216. X    stop_line = 0;
  1217. X    } else
  1218. X    stop_line = -1;
  1219. X
  1220. X next_line:
  1221. X
  1222. X    if (linenum == linemax) {
  1223. X    linemax += 500;
  1224. X    if (linepos == lineposbuf) {
  1225. X        linepos = newobj(off_t, linemax);
  1226. X        for (linenum = 0; linenum < LINEMAX; linenum++)
  1227. X        linepos[linenum] = lineposbuf[linenum];
  1228. X    } else
  1229. X        linepos = resizeobj(linepos, off_t, linemax);
  1230. X    }
  1231. X
  1232. X    if (goto_line == linenum) {
  1233. X    goto_line = -1;
  1234. X    goto next_page;
  1235. X    }
  1236. X
  1237. X    eof = 0;
  1238. X
  1239. X    if (linenum > maxline)
  1240. X    linepos[++maxline] = ftell(art);
  1241. X    else
  1242. X    if (linenum > 0)
  1243. X    fseek(art, linepos[linenum], 0);
  1244. X
  1245. X
  1246. X    if (linepos[linenum] >= ah->lpos) {
  1247. X    if (match_expr) {
  1248. X        match_expr = 0;
  1249. X        topline = match_topline;    /* LINT complaints here -- ignore */
  1250. X        linenum = match_botline;    /* LINT complaints here -- ignore */
  1251. X        fseek(art, linepos[linenum], 0);
  1252. X        msg("Not found");
  1253. X        goto Prompt;
  1254. X    }
  1255. X    eof++;
  1256. X    if (goto_line > 0) {
  1257. X        goto_line = -1;
  1258. X        linenum -= window_lines/2;
  1259. X        goto next_page;
  1260. X    }
  1261. X    goto Prompt;
  1262. X    }
  1263. X
  1264. X    if (linenum == 0) {
  1265. X    if (ftell(art) >= linepos[1]) {
  1266. X        linenum = 2;    /* current line is 1st line ! */
  1267. X        lno1 = lno;
  1268. X    }
  1269. X    } else
  1270. X    linenum++;
  1271. X
  1272. X    lp = linebuf;
  1273. X    col = 0;
  1274. X    form_feed = 0;
  1275. X
  1276. X next_char:
  1277. X
  1278. X    c = getc(art);
  1279. X    if (c == EOF) {
  1280. X    eof++;
  1281. X    if (lp == linebuf) goto Prompt;
  1282. X    goto end_line;
  1283. X    }
  1284. X
  1285. X    if (c & 0200) {
  1286. X    if (monitor_mode || data_bits != 8) {
  1287. X        col += 4;
  1288. X        if (col > Columns) {    /* then there is no room for M-^X */
  1289. X        ungetc(c, art);
  1290. X        goto long_line;
  1291. X        }
  1292. X        c &= 0177;
  1293. X        *lp++ = 'M';
  1294. X        *lp++ = '-';
  1295. X        if (c < SP) {
  1296. X        *lp++ = '^';
  1297. X        c += '@';
  1298. X        } else
  1299. X        col--;
  1300. X    }
  1301. X    } else
  1302. X    if (c < SP) {
  1303. X    if (monitor_mode) {
  1304. X        if (c == NL) {
  1305. X        *lp++ = '$';
  1306. X            goto end_line;
  1307. X        }
  1308. X        if (col + 2 > Columns) {
  1309. X        *lp++ = '\\';
  1310. X        ungetc(c, art);
  1311. X        goto end_line;
  1312. X        }
  1313. X        *lp++ = '^';
  1314. X        c += '@';
  1315. X        col++;
  1316. X    } else
  1317. X    switch (c) {
  1318. X
  1319. X     case '\f':
  1320. X        last_ff_line = linenum;
  1321. X        if (lp == linebuf) {
  1322. X        if (goto_line > 0 || skip_char || match_expr || lno == lno1)
  1323. X            goto next_line;
  1324. X        form_feed = 1;
  1325. X        goto Prompt;
  1326. X        }
  1327. X        form_feed = 1;
  1328. X        goto end_line;
  1329. X
  1330. X     case CR:
  1331. X        if (lp == linebuf || ignore_nl) goto next_char;
  1332. X        ignore_nl = 1;
  1333. X        goto end_line;
  1334. X
  1335. X     case NL:
  1336. X        if (ignore_nl) {
  1337. X        ignore_nl = 0;
  1338. X        if (lp == linebuf) {
  1339. X            if (lno == lno1) {
  1340. X            ignore_nl = 1;
  1341. X            goto next_line;
  1342. X            }
  1343. X            goto next_char;
  1344. X        }
  1345. X        }
  1346. X        goto end_line;
  1347. X
  1348. X     case BS:
  1349. X        if (col) {
  1350. X        lp--;
  1351. X        col--;
  1352. X        }
  1353. X        goto next_char;
  1354. X
  1355. X     case TAB:
  1356. X        if (col + 8 - (col & 07) >= Columns)
  1357. X        goto long_line;
  1358. X
  1359. X        do {
  1360. X        *lp++ = SP;
  1361. X        col++;
  1362. X        } while (col & 07);
  1363. X        goto next_char;
  1364. X
  1365. X     default:
  1366. X        if (col + 2 > Columns) {
  1367. X        ungetc(c, art);
  1368. X        goto long_line;
  1369. X        }
  1370. X        *lp++ = '^';
  1371. X        c += '@';
  1372. X        col++;
  1373. X        break;
  1374. X    }
  1375. X    }
  1376. X
  1377. X    *lp++ = c;
  1378. X    col++;
  1379. X    ignore_nl = 0;
  1380. X
  1381. X    if (col < Columns) goto next_char;
  1382. X
  1383. Xlong_line:
  1384. X    ignore_nl = 1;
  1385. X
  1386. X end_line:
  1387. X    /* if we are seaching for a specific line, repeat until it is found */
  1388. X    if (skip_wrap) {
  1389. X    skip_wrap = ignore_nl;
  1390. X    goto next_line;
  1391. X    }
  1392. X    if (goto_line >= linenum) goto next_line;
  1393. X    if (skip_char) {
  1394. X    if (lp == linebuf || linebuf[0] == skip_char) {
  1395. X        skip_wrap = ignore_nl;
  1396. X        goto next_line;
  1397. X    }
  1398. X    skip_char = NUL;
  1399. X    if (overlap > 0) {
  1400. X        underline_line = linenum;
  1401. X        linenum -= overlap;
  1402. X        goto next_page;
  1403. X    }
  1404. X    }
  1405. X
  1406. X    *lp++ = NUL;
  1407. X
  1408. X    if (match_expr) {
  1409. X    if (!regexec_cf(regular_expr, linebuf))
  1410. X        goto next_line;
  1411. X    match_expr = 0;
  1412. X    match_lines = 1;
  1413. X    if (linenum > match_botline) {
  1414. X        match_redraw = 0;
  1415. X        if (last_ff_line > linenum) last_ff_line = -1;
  1416. X        linenum -= 5;
  1417. X        if (linenum < last_ff_line) linenum = last_ff_line;
  1418. X        goto next_page;
  1419. X    }
  1420. X    match_redraw = (stop_line < 0);
  1421. X    stop_line = -1;
  1422. X    lno = lno1 + linenum - topline - 1;
  1423. X    print_lines = window_lines - lno + lno1;
  1424. X    }
  1425. X
  1426. X    /* now print the line */
  1427. X
  1428. X    if (match_lines && underline_line != linenum &&
  1429. X    regexec_cf(regular_expr, linebuf)) {
  1430. X    match_start = regular_expr->startp[0];
  1431. X    match_end = regular_expr->endp[0];
  1432. X    } else {
  1433. X    if (match_redraw) goto no_print;
  1434. X    match_start = NULL;
  1435. X    }
  1436. X
  1437. X    gotoxy(0, lno);
  1438. X    if (!scroll_clear_page) clrline();
  1439. X
  1440. X    if (mark_overlap && underline_line == linenum)
  1441. X    if (!underline(1))
  1442. X        fake_underline = 1;
  1443. X    skip_spaces = has_space = 0;
  1444. X
  1445. X    for (lp = linebuf; c = *lp; lp++) {
  1446. X
  1447. X    if (match_start) {
  1448. X        if (lp == match_start) highlight(1);
  1449. X        if (lp == match_end) {
  1450. X        highlight(0);
  1451. X        match_start = NULL;
  1452. X        if (match_redraw) goto no_print;
  1453. X        }
  1454. X    }
  1455. X
  1456. X    if (c == SP) {
  1457. X        if (skip_spaces) {
  1458. X        if (has_space) continue;
  1459. X        has_space++;
  1460. X        }
  1461. X        if (fake_underline) c = '_';
  1462. X    } else {
  1463. X        if (compress_space && c != ' ') {
  1464. X        skip_spaces = 1;
  1465. X        has_space = 0;
  1466. X        }
  1467. X        if (rot13_active && linenum > 0)
  1468. X        c = ROT13_DECODE(c);
  1469. X    }
  1470. X
  1471. X    putchar(c);
  1472. X    }
  1473. X
  1474. X    if (match_start) highlight(0);
  1475. X
  1476. X    if (mark_overlap && underline_line == linenum) {
  1477. X    while (lp - linebuf < 10) {
  1478. X        putchar(fake_underline ? '_' : ' ');
  1479. X        lp++;
  1480. X    }
  1481. X    underline(0);
  1482. X    underline_line = -1;
  1483. X    fake_underline = 0;
  1484. X    }
  1485. X
  1486. Xno_print:
  1487. X
  1488. X    ++lno;
  1489. X    if (--print_lines > 0 && s_keyboard == 0 && form_feed == 0) goto next_line;
  1490. X
  1491. X    if (!eof && linenum >= maxline) {
  1492. X    if (ignore_nl) {
  1493. X        c = getc(art);
  1494. X        if (c == EOF)
  1495. X        eof++;
  1496. X        else if (c != NL)
  1497. X        ungetc(c, art);
  1498. X        else
  1499. X        ignore_nl = 0;
  1500. X    }
  1501. X
  1502. X    if (!eof && ftell(art) >= ah->lpos) eof++;
  1503. X    }
  1504. X
  1505. X    match_redraw = 0;
  1506. X
  1507. X Prompt:
  1508. X
  1509. X    if (eof && lno == screen_offset) more_return(MC_NEXT);
  1510. X
  1511. X    raw();
  1512. X
  1513. X    prompt_line = lno;
  1514. X
  1515. X    if (!scroll_clear_page)
  1516. X    clrpage(prompt_line);
  1517. X
  1518. X dflt_prompt:
  1519. X
  1520. X    prompt(pr_fmt,
  1521. X       pct((long)(ah->fpos), (long)(ah->lpos),
  1522. X           (long)(linepos[topline]), (long)ftell(art)),
  1523. X       a_st_flags(ah->flag));
  1524. X
  1525. X    if (delayed_msg[0] != NUL) {
  1526. X    msg(delayed_msg);
  1527. X    delayed_msg[0] = NUL;
  1528. X    }
  1529. X
  1530. X same_prompt:
  1531. X
  1532. X    if (flush_typeahead) flush_input();
  1533. X
  1534. X    if ((c = get_c()) & GETC_COMMAND)
  1535. X    c &= ~GETC_COMMAND;
  1536. X    else
  1537. X    c = more_key_map[c];
  1538. X
  1539. X    if (s_hangup) c = K_QUIT;
  1540. X
  1541. X    if (any_message) clrmsg(0);
  1542. X
  1543. X    if (c & K_MACRO) {
  1544. X    m_invoke(c & ~K_MACRO);
  1545. X    goto same_prompt;
  1546. X    }
  1547. X
  1548. X alt_key:
  1549. X
  1550. X    switch (c) {
  1551. X     case K_UNBOUND:
  1552. X    ding();
  1553. X     case K_INVALID:
  1554. X    goto same_prompt;
  1555. X
  1556. X     case K_REDRAW:
  1557. X#ifdef RESIZING
  1558. X    if (Columns != entry_col) {
  1559. X        entry_col = Columns;
  1560. X        maxline = topline = 1;
  1561. X    }
  1562. X#endif
  1563. X     goto redraw;
  1564. X
  1565. X     case K_NEXT_PAGE:
  1566. X    if (eof) {
  1567. X        ding();
  1568. X        goto same_prompt;
  1569. X    }
  1570. X    /* FALL THRU */
  1571. X
  1572. X     case K_CONTINUE:
  1573. X    if (eof) break;
  1574. X    if (screen_offset == 0 && form_feed == 0 && stop_line) {
  1575. X        if (linenum > overlap) {
  1576. X        underline_line = linenum;
  1577. X        linenum -= overlap;
  1578. X        }
  1579. X    }
  1580. X    goto next_page;
  1581. X
  1582. X     case K_LAST_MESSAGE:
  1583. X    msg((char *)NULL);
  1584. X    goto dflt_prompt;
  1585. X
  1586. X     case K_HELP:
  1587. X    display_help("more");
  1588. X    goto redraw;
  1589. X
  1590. X     case K_SHELL:
  1591. X    putchar(CR);
  1592. X    if (shell_escape()) goto redraw;
  1593. X    goto dflt_prompt;
  1594. X
  1595. X     case K_EXTENDED_CMD:
  1596. X    news_save = news;
  1597. X    digest_save = digest;
  1598. X    more_cmd = alt_command();
  1599. X    news = news_save;
  1600. X    digest = digest_save;
  1601. X
  1602. X    switch (more_cmd) {
  1603. X
  1604. X     case AC_UNCHANGED:
  1605. X        goto same_prompt;
  1606. X
  1607. X     case AC_QUIT:
  1608. X        more_return( MC_QUIT );
  1609. X
  1610. X     case AC_PROMPT:
  1611. X        goto dflt_prompt;
  1612. X
  1613. X     case AC_REENTER_GROUP:
  1614. X        more_return( MC_REENTER_GROUP );
  1615. X
  1616. X     case AC_REORDER:
  1617. X        more_return( MC_MENU );
  1618. X
  1619. X     case AC_REDRAW:
  1620. X        goto redraw;
  1621. X
  1622. X     case AC_KEYCMD:
  1623. X        c = alt_cmd_key;
  1624. X        goto alt_key;
  1625. X    }
  1626. X
  1627. X     case K_QUIT:
  1628. X    ah->attr = A_LEAVE_NEXT;
  1629. X    more_return( MC_QUIT );
  1630. X
  1631. X     case K_SAVE_NO_HEADER:
  1632. X     case K_SAVE_SHORT_HEADER:
  1633. X     case K_SAVE_FULL_HEADER:
  1634. X     case K_PRINT:
  1635. X     case K_UNSHAR:
  1636. X     case K_PATCH:
  1637. X     case K_UUDECODE:
  1638. X    news_save = news;
  1639. X    digest_save = digest;
  1640. X
  1641. X    putchar(CR);
  1642. X    if (init_save(c, (char **)NULL) != NULL) {
  1643. X        if (c == K_UNSHAR)
  1644. X        prompt_line = Lines - 2;
  1645. X
  1646. X        save(ah);
  1647. X        end_save();
  1648. X    }
  1649. X    news = news_save;
  1650. X    digest = digest_save;
  1651. X    if (!slow_mode && (c == K_UNSHAR || c == K_PATCH)) {
  1652. X        printf("\r\n\n");
  1653. X        any_key(0);
  1654. X        goto redraw;
  1655. X    }
  1656. X    goto Prompt;
  1657. X
  1658. X     case K_FOLLOW_UP:
  1659. X#ifdef NNTP_POST
  1660. X     if (use_nntp && nntp_no_post()) goto Prompt;
  1661. X#endif
  1662. X     case K_REPLY:
  1663. X     case K_MAIL_OR_FORWARD:
  1664. X    news_save = news;
  1665. X    digest_save = digest;
  1666. X    more_cmd = answer(ah, c, -1);
  1667. X    news = news_save;
  1668. X    digest = digest_save;
  1669. X    if (more_cmd)
  1670. X        if (slow_mode) clrdisp(); else goto redraw;
  1671. X    goto Prompt;
  1672. X
  1673. X     case K_POST:
  1674. X    if (post_menu())
  1675. X        if (slow_mode) clrdisp(); else goto redraw;
  1676. X    goto Prompt;
  1677. X
  1678. X     case K_CANCEL:
  1679. X    if (current_group->group_flag & G_FOLDER) {
  1680. X        prompt("%s this folder entry",
  1681. X           (ah->attr == A_CANCEL) ? "UNcancel" : "Cancel");
  1682. X        if (yes(0)) fcancel(ah);
  1683. X        goto Prompt;
  1684. X    }
  1685. X
  1686. X    if (cancel(ah) > 0) goto Prompt;
  1687. X    more_return(MC_NEXT);
  1688. X
  1689. X     case K_UNSUBSCRIBE:
  1690. X    if (!unsubscribe(current_group)) goto Prompt;
  1691. X    if ((current_group->group_flag & G_UNSUBSCRIBED) == 0) goto Prompt;
  1692. X    more_return(MC_NEXTGROUP);
  1693. X
  1694. X     case K_GROUP_OVERVIEW:
  1695. X    group_overview(-1);
  1696. X    goto redraw;
  1697. X
  1698. X     case K_KILL_HANDLING:
  1699. X    switch (kill_menu(ah)) {
  1700. X     case 0:
  1701. X        more_return(MC_DO_SELECT);
  1702. X     case 1:
  1703. X        more_return(MC_DO_KILL);
  1704. X     default:
  1705. X        break;
  1706. X    }
  1707. X    goto Prompt;
  1708. X
  1709. X     case K_READ_GROUP_UPDATE:
  1710. X    if (mode & MM_PREVIEW) more_return(MC_MENU);
  1711. X    prompt("Mark rest of current group as read?");
  1712. X    if (yes(1) <= 0) goto Prompt;
  1713. X    more_return(MC_READGROUP);
  1714. X
  1715. X     case K_NEXT_GROUP_NO_UPDATE:
  1716. X    if (mode & MM_PREVIEW) more_return(MC_MENU);
  1717. X    more_return(MC_NEXTGROUP);
  1718. X
  1719. X     case K_BACK_TO_MENU:
  1720. X    more_return(MC_MENU);
  1721. X
  1722. X     case K_PREVIOUS:
  1723. X    if ((mode & MM_PREVIOUS) == 0) {
  1724. X        msg("No previous article");
  1725. X        goto dflt_prompt;
  1726. X    }
  1727. X    more_return(MC_PREV);
  1728. X
  1729. X     case K_ADVANCE_GROUP:
  1730. X     case K_BACK_GROUP:
  1731. X     case K_GOTO_GROUP:
  1732. X    news_save = news;
  1733. X    digest_save = digest;
  1734. X    more_cmd = goto_group(c, ah, (flag_type)0);
  1735. X    news = news_save;
  1736. X    digest = digest_save;
  1737. X
  1738. X    switch (more_cmd) {
  1739. X     case ME_NO_REDRAW:
  1740. X        goto Prompt;
  1741. X
  1742. X     case ME_QUIT:
  1743. X        more_return( ME_QUIT );
  1744. X
  1745. X     default:
  1746. X        goto redraw;
  1747. X    }
  1748. X
  1749. X     case K_NEXT_LINE:
  1750. X    if (eof) break;
  1751. X    if (screen_offset) goto same_prompt;
  1752. X
  1753. X    print_lines = 1;
  1754. X    goto scroll;
  1755. X
  1756. X     case K_NEXT_HALF_PAGE:
  1757. X    if (eof) break;
  1758. X    if (screen_offset) goto same_prompt;
  1759. X
  1760. X    print_lines = window_lines/2;
  1761. X
  1762. X     scroll:
  1763. X    gotoxy(0, prompt_line);
  1764. X    clrpage(prompt_line);
  1765. X    no_raw();
  1766. X
  1767. X    if (print_lines + lno < (Lines - 1))
  1768. X        goto next_page;
  1769. X
  1770. X    stop_line = -1;
  1771. X    gotoxy(0, Lines-1);
  1772. X    c = print_lines + lno - Lines + 2;
  1773. X    while (--c >= 0) {
  1774. X        putchar(NL);
  1775. X        if (--lno1 < 0) topline++;
  1776. X        prompt_line--;
  1777. X    }
  1778. X    if (lno1 < 0) lno1 = 0;
  1779. X    if (prompt_line < 0) prompt_line = 0;
  1780. X    lno = prompt_line;
  1781. X    goto next_line;
  1782. X
  1783. X     case K_PREV_HALF_PAGE:
  1784. X    if (topline <= 1) goto Prompt;
  1785. X    linenum = topline - window_lines/2;
  1786. X    if (linenum < 1) linenum = 1;
  1787. X    goto next_page;
  1788. X
  1789. X     case K_PREV_PAGE:
  1790. X    if (topline <= 1) goto Prompt;
  1791. X    linenum = topline - window_lines + overlap; /* not perfect after FF */
  1792. X    underline_line = topline;
  1793. X    if (linenum < 1) linenum = 1;
  1794. X    goto next_page;
  1795. X
  1796. X     case K_SKIP_LINES:
  1797. X    skip_char = linebuf[0];
  1798. X    goto next_page;
  1799. X
  1800. X     case K_GOTO_LINE:
  1801. X    prompt("\1Go to line:\1 ");
  1802. X    if ((fname = get_s(NONE, NONE, "$^", NULL_FCT)) == NULL)
  1803. X        goto Prompt;
  1804. X
  1805. X    if (*fname == NUL) {
  1806. X        if (prev_goto < 0) goto Prompt;
  1807. X        goto_line = prev_goto;
  1808. X
  1809. X    } else
  1810. X    if (*fname == '$')
  1811. X        goto_line = 30000;
  1812. X    else
  1813. X    if (*fname == '^')
  1814. X        goto_line = 1;
  1815. X    else {
  1816. X        goto_line = atoi(fname);
  1817. X        if (goto_line <= 0) {
  1818. X        goto_line = -1;
  1819. X        goto Prompt;
  1820. X        }
  1821. X    }
  1822. X
  1823. X     goto_page:
  1824. X    prev_goto = topline;
  1825. X
  1826. X    if (goto_line <= maxline) {
  1827. X        linenum = goto_line;
  1828. X        goto_line = -1;
  1829. X    }
  1830. X
  1831. X    goto next_page;
  1832. X
  1833. X     case K_SELECT_SUBJECT:
  1834. X    more_return(MC_ALLSUBJ);
  1835. X
  1836. X     case K_HEADER_PAGE:
  1837. X    fseek(art, linepos[0], 0);
  1838. X    goto_line = 0;
  1839. X    goto goto_page;
  1840. X
  1841. X     case K_FIRST_PAGE:
  1842. X    goto_line = 1;
  1843. X    goto goto_page;
  1844. X
  1845. X     case K_LAST_PAGE:
  1846. X    goto_line = 30000;
  1847. X    goto goto_page;
  1848. X
  1849. X     case K_GOTO_MATCH:
  1850. X    prompt("\1/\1");
  1851. X    if ((fname = get_s(NONE, NONE, "/", NULL_FCT)) == NULL)
  1852. X        goto Prompt;
  1853. X
  1854. X    if (*fname && *fname != '/') {
  1855. X        if (regular_expr) freeobj(regular_expr);
  1856. X        if (case_fold_search) fold_string(fname);
  1857. X        regular_expr = regcomp(fname);
  1858. X    }
  1859. X
  1860. X     case K_NEXT_MATCH:
  1861. X    if (regular_expr == NULL) {
  1862. X        msg("No previous expression");
  1863. X        goto Prompt;
  1864. X    }
  1865. X
  1866. X    match_expr = 1;
  1867. X    if (match_topline != topline) prev_goto = topline;
  1868. X    match_topline = topline;
  1869. X    match_botline = linenum;
  1870. X    if (match_lines == 0 && topline <= 1) linenum = topline;
  1871. X    match_lines = 0;
  1872. X    goto next_line;        /* don't clear the screen if no match */
  1873. X
  1874. X     case K_FULL_DIGEST:
  1875. X    if (mode & MM_DIGEST)
  1876. X        more_return( MC_NO_REDRAW );
  1877. X
  1878. X    if (!in_digest)
  1879. X        goto same_prompt;
  1880. X
  1881. X    /* could do something more clever here later */
  1882. X    digestah = *ah;
  1883. X    digestah.flag &= ~A_DIGEST;
  1884. X    digestah.hpos = digestah.fpos = 0;
  1885. X    fseek(art, 0L, 2);
  1886. X    digestah.lpos = ftell(art);
  1887. X
  1888. X    switch (more(&digestah, mode | MM_DIGEST, screen_offset)) {
  1889. X
  1890. X     case MC_REDRAW:
  1891. X        goto redraw;
  1892. X
  1893. X     case MC_NO_REDRAW:
  1894. X        goto safe_redraw;
  1895. X
  1896. X     case MC_QUIT:
  1897. X        more_return( MC_QUIT );
  1898. X
  1899. X     case MC_REENTER_GROUP:
  1900. X        more_return( MC_REENTER_GROUP );
  1901. X
  1902. X     default:
  1903. X        goto safe_redraw;
  1904. X    }
  1905. X
  1906. X     case K_LEAVE_NEXT:
  1907. X    ah->attr = A_LEAVE_NEXT;
  1908. X    more_return(MC_PREVIEW_NEXT);
  1909. X
  1910. X     case K_LEAVE_ARTICLE:
  1911. X    ah->attr = (mode & MM_PREVIEW) ? A_SELECT : A_LEAVE;
  1912. X    /* fall thru */
  1913. X
  1914. X     case K_NEXT_ARTICLE:
  1915. X    if ((mode & MM_PREVIEW) == 0) break;
  1916. X    more_return(MC_PREVIEW_NEXT);
  1917. X
  1918. X     case K_BACK_ARTICLE:
  1919. X    if (mode & MM_FIRST_ARTICLE) {
  1920. X        msg("First article is displayed");
  1921. X        goto same_prompt;
  1922. X    }
  1923. X    more_return(MC_BACK_ART);
  1924. X
  1925. X     case K_FORW_ARTICLE:
  1926. X    if (mode & MM_LAST_ARTICLE) {
  1927. X        msg("Last article is displayed");
  1928. X        goto same_prompt;
  1929. X    }
  1930. X    more_return(MC_FORW_ART);
  1931. X
  1932. X     case K_NEXT_SUBJECT:
  1933. X    more_return(MC_NEXTSUBJ);
  1934. X
  1935. X     case K_ROT13:
  1936. X    if (rot13_must_init) {
  1937. X        register i;
  1938. X        for (i=0; i<=127; i++) {
  1939. X        c = i;
  1940. X        if (c >= 'a' && c <= 'm') c += 13;
  1941. X        else if (c >= 'n' && c <= 'z') c -= 13;
  1942. X        else if (c >= 'A' && c <= 'M') c += 13;
  1943. X        else if (c >= 'N' && c <= 'Z') c -= 13;
  1944. X        rot13_table[i] = c;
  1945. X        }
  1946. X        rot13_must_init = 0;
  1947. X    }
  1948. X
  1949. X    rot13_active = !rot13_active;
  1950. X    goto safe_redraw;
  1951. X
  1952. X     case K_COMPRESS:
  1953. X    compress_space = !compress_space;
  1954. X    goto safe_redraw;
  1955. X
  1956. X     case K_PREVIEW:
  1957. X    if (mode & MM_PREVIEW)
  1958. X        more_return(MC_PREVIEW_OTHER);
  1959. X
  1960. X    /* fall thru to "default" */
  1961. X
  1962. X     default:
  1963. X    msg("Command %d not supported", c);
  1964. X    goto dflt_prompt;
  1965. X    }
  1966. X
  1967. X    more_return(MC_NEXT);
  1968. X
  1969. X more_exit:
  1970. X    in_menu_mode = o_mode;
  1971. X    rot13_active = 0;
  1972. X
  1973. X    if (linepos != lineposbuf) freeobj(linepos);
  1974. X
  1975. X    no_raw();
  1976. X    fclose(art);
  1977. X
  1978. X    if (mode & MM_PREVIEW)
  1979. X    if (more_cmd != MC_QUIT && more_cmd != MC_REENTER_GROUP) {
  1980. X        gotoxy(0, screen_offset);
  1981. X        clrpage(screen_offset);
  1982. X        if (auto_preview_mode && ah->attr == 0)
  1983. X        ah->attr = A_READ;
  1984. X        if (screen_offset == 0) prompt_line = -1;
  1985. X    }
  1986. X
  1987. X    return more_cmd;
  1988. X}
  1989. X
  1990. X
  1991. Xrot13_line(cp)
  1992. Xregister char *cp;
  1993. X{
  1994. X    register int c;
  1995. X
  1996. X    while (c = *cp)
  1997. X    *cp++ = ROT13_DECODE(c);
  1998. X}
  1999. X
  2000. END_OF_FILE
  2001.   if test 24124 -ne `wc -c <'more.c'`; then
  2002.     echo shar: \"'more.c'\" unpacked with wrong size!
  2003.   fi
  2004.   # end of 'more.c'
  2005. fi
  2006. echo shar: End of archive 9 \(of 22\).
  2007. cp /dev/null ark9isdone
  2008. MISSING=""
  2009. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
  2010.     if test ! -f ark${I}isdone ; then
  2011.     MISSING="${MISSING} ${I}"
  2012.     fi
  2013. done
  2014. if test "${MISSING}" = "" ; then
  2015.     echo You have unpacked all 22 archives.
  2016.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2017. else
  2018.     echo You still must unpack the following archives:
  2019.     echo "        " ${MISSING}
  2020. fi
  2021. exit 0
  2022.  
  2023. exit 0 # Just in case...
  2024.